package com.vichat.common.rudp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;


public class ProtocolUtil {

    private static transient Logger logger = LoggerFactory.getLogger(ProtocolUtil.class);
    
	/*
    public static int byte2int(byte[] indata,int datalen){
        int mask=0xff;
        int temp=0;
        int n=0;
        for(int i=0;i<datalen;i++){
            temp=(indata[i]&mask)<<8*i;
            n|=temp;
        }
        return n;
    }


    public static byte[] int2byte(int iSource, int iArrayLen) {
        byte[] bLocalArr = new byte[iArrayLen];
        for (int i = 0; (i < 4) && (i < iArrayLen); i++) {
            bLocalArr[i] = (byte) (iSource >> 8 * i & 0xFF);
        }
        return bLocalArr;
    }
*/

    public static byte[] int2sizebyte(int iSource) {
        byte[] intArray = new byte[3];
        intArray[0] = (byte) (iSource >> 16 & 0xFF);
        intArray[1] = (byte) (iSource >> 8 & 0xFF);
        intArray[2] = (byte) (iSource & 0xFF);

        return intArray;
    }

    public static byte[] int2byte(int iSource) {
        byte[] intArray;
        if (iSource < 255) {
            intArray = new byte[1];
            intArray[0] = (byte) (iSource & 0xff);
        } else {
            intArray = new byte[5];
            intArray[0] = (byte) 0xff;
            intArray[1] = (byte) (iSource >> 24 & 0xFF);
            intArray[2] = (byte) (iSource >> 16 & 0xFF);
            intArray[3] = (byte) (iSource >> 8 & 0xFF);
            intArray[4] = (byte) (iSource & 0xFF);
        }
        return intArray;
    }

    public static int byte2int(byte[] inbytes) {
        int val = 0;
        if (inbytes.length == 1) {
            val = inbytes[0] & 0xff;
        } else if (inbytes.length == 4) {
            int tmp = (0xff & inbytes[0]) << 24;
            val |= tmp;
            tmp = (0xff & inbytes[1]) << 16;
            val |= tmp;
            tmp = (0xff & inbytes[2]) << 8;
            val |= tmp;
            tmp = 0xff & inbytes[3];
            val |= tmp;
        } else {
            val = -9999;
        }
        return val;
    }


    public static int decodeSize(ParseData parseData) {
        int dataSize = 0;
        if (parseData.dataArray[parseData.startPos] == (byte) 0xFF) {
            byte[] tmpByteArray = new byte[4];
            parseData.startPos += 1;
            System.arraycopy(parseData.dataArray, parseData.startPos, tmpByteArray, 0, 4);
            dataSize = ProtocolUtil.byte2int(tmpByteArray);
            parseData.startPos += 4;
        } else {
            byte sizeData = parseData.dataArray[parseData.startPos];
            dataSize = sizeData & 0x0FF;
            parseData.startPos += 1;
        }
        //Log.d("##ProtocolUtil","decodeSize:"+dataSize+";"+parseData.startPos);
        return dataSize;
    }

    public static HashMap<Integer, String> decodeMap(ParseData parseData) {
        HashMap<Integer, String> resMap = null;
        try {
            logger.debug("##ProtocolUtil decodeMap:dataLenth" + parseData.dataArray.length + ";" + parseData.startPos);
            int kvSize = ProtocolUtil.decodeSize(parseData);
            logger.debug("##ProtocolUtil decodeMap:kvsize " + kvSize);
            if (kvSize > 0) {
                resMap = new HashMap<Integer, String>();
                for (int vi = 0; vi < kvSize; vi++) {
                    try {
                        int key = ProtocolUtil.decodeSize(parseData);
                        //String strKey = String.valueOf(key);
                        int valSize = ProtocolUtil.decodeSize(parseData);
                        String strVal = "";
                        if (valSize > 0) {
                            byte[] valArray = new byte[valSize];
                            System.arraycopy(parseData.dataArray, parseData.startPos, valArray, 0, valSize);
                            strVal = new String(valArray);
                            parseData.startPos += valSize;
                        }
                        resMap.put(new Integer(key), strVal);
                        //Log.d("##ProtocolUtil","decode mapkv: key"+key+";val-"+strVal);
                    } catch (Exception e) {
//                        logger.error("!!ProtocolUtil decode mapkv error" + vi, e);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("!!ProtocolUtil decode mapkv error", e);
        }
        return resMap;
    }

    public static byte[] encodeMap(HashMap<Integer, String> paramsMap) {
        int kvSize = paramsMap.size();
        ArrayList<ParseData> paramList = new ArrayList<ParseData>(kvSize);
        byte[] kvByte = int2byte(kvSize);
        int totalLen = kvByte.length;
        for (Iterator<Integer> iter = paramsMap.keySet().iterator(); iter.hasNext(); ) {
            try {
                Integer key = iter.next();
                
                
                byte[] keyByte = int2byte(key.intValue());
//                logger.debug("##ProtocolUtil encodeMap key-" + key + "," + keyByte.length + "," + keyByte[0]);
                int keySize = keyByte.length;
                int sumSize = keySize;
                
                String paramstr = "";
                if(paramsMap.get(key)!=null){
                	paramstr = paramsMap.get(key);
                }
                
                byte[] paramsVal = paramstr.getBytes("UTF-8");
                int paramSize = paramsVal.length;
                sumSize += paramSize;
                byte[] paramSizeByte = int2byte(paramSize);
//                logger.debug("##ProtocolUtil encodeMap paramSize-" + paramSize + "," + paramSizeByte.length + "," + paramSizeByte[0]);
                int paramSizeSize = paramSizeByte.length;
                sumSize += paramSizeSize;
                byte[] paramByte = new byte[sumSize];
                System.arraycopy(keyByte, 0, paramByte, 0, keySize);
                System.arraycopy(paramSizeByte, 0, paramByte, keySize, paramSizeSize);
                System.arraycopy(paramsVal, 0, paramByte, keySize + paramSizeSize, paramSize);
                ParseData oneData = new ParseData(paramByte);
                paramList.add(oneData);
                totalLen += sumSize;
            } catch (Exception e) {
                logger.error("!!ProtocolUtil encodeMap error" + e);
            }
        }
        byte[] mapbytes = new byte[totalLen];
        System.arraycopy(kvByte, 0, mapbytes, 0, kvByte.length);
        int ipos = kvByte.length;
        for (Iterator<ParseData> iter = paramList.iterator(); iter.hasNext(); ) {
            byte[] onebytes = iter.next().dataArray;
            System.arraycopy(onebytes, 0, mapbytes, ipos, onebytes.length);
            ipos += onebytes.length;
        }
        return mapbytes;

    }


    public static HashMap<Integer, ParseData> decodeCallbakData(ParseData cbdata, boolean debuginfo) {
        HashMap<Integer, ParseData> resMap = null;
        if (debuginfo) {
            logger.debug("##ProtocolUtil parseCallbakData:dataLenth" + cbdata.dataArray.length + ";" + cbdata.toString());
        }
        int kvSize = ProtocolUtil.decodeSize(cbdata);
        if (kvSize > 0) {
            resMap = new HashMap<Integer, ParseData>(kvSize, 1f);
            for (int vi = 0; vi < kvSize; vi++) {
                try {
                    int key = ProtocolUtil.decodeSize(cbdata);
                    //String strKey = String.valueOf(key);
                    int valSize = ProtocolUtil.decodeSize(cbdata);
                    if (valSize > 0) {
                        byte[] valArray = new byte[valSize];
                        System.arraycopy(cbdata.dataArray, cbdata.startPos, valArray, 0, valSize);
                        cbdata.startPos += valSize;
                        ParseData paramdata = new ParseData(valArray);
                        resMap.put(new Integer(key), paramdata);
                        if (debuginfo) {
                            logger.debug("##ProtocolUtil decode mapkv: key" + key + ";valsize-" + valSize);
                        }
                    } else {
                        resMap.put(new Integer(key), null);
                        if (debuginfo) {
                            logger.debug("##ProtocolUtil decode mapkv: key" + key + ";val-null");
                        }
                    }

                } catch (Exception e) {
                    logger.error("!!ProtocolUtil decode mapkv error" + e.toString());
                }
            }
        }
        return resMap;
    }

    public static String transIdStr(byte[] transId){
        StringBuilder traninfo = new StringBuilder();
        for (int tt = 0; tt < transId.length; tt++) {
            traninfo.append(transId[tt]).append("-");
        }
        return traninfo.toString();
    }


}
